package bsf.db.pool;

import bsf.base.BsfException;
import bsf.base.CallBack;
import bsf.db.base.DbConfigBase;
import bsf.db.base.DbException;
import bsf.db.driver.sqlserver.DbConfigSqlServerWithDruid;
import bsf.system.configparser.ConfigStringParserManager;
import bsf.util.StringUtil;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by chejiangyi on 2016/3/4.
 * Druid连接池使用简化及二次封装使用
 */
public class ConnectionPoolHelper {
    private static class ConnectionPool {
        private ConcurrentHashMap<String, Object> pool = new ConcurrentHashMap<>();
        private Object poolLock = new Object();

        public Object tryGet(String key, CallBack.Func1<Object, String> func) {
            Object c = pool.get(key);
            if (c == null) {
                synchronized (poolLock) {
                    c = pool.get(key);
                    if (c == null) {
                        c = func.invoke(key);
                        pool.put(key,c);
                        c=pool.get(key);
                    }
                }
            }
            return c;
        }


    }

    private static ConnectionPool connectionPool = new ConnectionPool();

    public static Connection getConnection(String connectString) {
        try {
            final DbConfigBase configBase = new ConfigStringParserManager().GetParser(DbConfigBase.class).Parse(connectString, DbConfigBase.class);

            if ("druid".equalsIgnoreCase(configBase.PoolType)) {
                if ("sqlserver".equalsIgnoreCase(configBase.Type)) {
                   Object dataSource = connectionPool.tryGet(connectString, new CallBack.Func1<Object, String>() {
                        @Override
                        public Object invoke(String connectString) {
                            try {
                                Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
                            } catch (Exception exp) {
                                throw new BsfException("请引入sqlserver连接驱动sqljdbc.jar包", exp, ConnectionPoolHelper.class);
                            }
                            DbConfigSqlServerWithDruid config = new ConfigStringParserManager().GetParser(DbConfigSqlServerWithDruid.class).Parse(connectString, DbConfigSqlServerWithDruid.class);
                            config.init(configBase);
                            HashMap<String, String> druidMap = new HashMap();
                            druidMap.put(DruidDataSourceFactory.PROP_URL, config.Url);
                            druidMap.put(DruidDataSourceFactory.PROP_USERNAME, config.UserName);
                            druidMap.put(DruidDataSourceFactory.PROP_PASSWORD, config.Password);
                            druidMap.put(DruidDataSourceFactory.PROP_DRIVERCLASSNAME, config.DriverClassName);
                            druidMap.put(DruidDataSourceFactory.PROP_INITIALSIZE, config.InitialSize + "");
                            druidMap.put(DruidDataSourceFactory.PROP_MAXACTIVE, config.MaxActive + "");
                            druidMap.put(DruidDataSourceFactory.PROP_MINIDLE, config.MinIdle + "");
                            druidMap.put(DruidDataSourceFactory.PROP_TESTWHILEIDLE, config.TestWhileIdle + "");

                            try {
                                DataSource dataSource = DruidDataSourceFactory.createDataSource(druidMap);
                                return dataSource;
                            }
                            catch (Exception exp)
                            {
                                throw new BsfException("初始化druid DataSource:"+config.toString(),exp);
                            }
                        }
                    });
                    Connection conn =((DataSource)dataSource).getConnection();
                    return conn;
                }
            }
        } catch (Exception exp) {
            throw new DbException("数据库连接字符串解析获取连接出错:"+ StringUtil.nullToEmpty( connectString), exp, ConnectionPoolHelper.class);
        }
        throw new DbException("未找到相应的数据库连接解析驱动:"+ StringUtil.nullToEmpty( connectString), ConnectionPoolHelper.class);
    }
}

